package admin

import (
	"errors"
	"exercise/application/yiran/app"
	"exercise/application/yiran/app/libs"
	"exercise/application/yiran/app/model"
	"exercise/application/yiran/app/request/adminRequest"
	"exercise/application/yiran/app/service"
	"fmt"
	"github.com/gin-gonic/gin"
	"path/filepath"
	"reflect"
	"strings"
)

type studentScoreService struct {
	req *gin.Context
}

// InitStudent 初始化学生
func (rev *studentScoreService) InitStudent(request *adminRequest.InitStudentRequest) (err error) {
	schoolId, _ := rev.req.Get("schoolId")
	rule := new(model.StudentScoreRule)
	query := model.NewDb("").Query()
	err = query.Where("id = ?", request.RuleId).First(rule).Error
	if err != nil {
		return fmt.Errorf("获取规则异常：%w", err)
	}

	if rule.JsRange == "" {
		return errors.New("学生范围必须存在")
	}

	sql, where := NewScoreRuleService(rev.req).GetJsStudentRange(rule.JsRange)
	sql += " AND year = ? "
	where = append(where, request.Year)

	studentList := make([]model.ExamStudent18817, 0)
	err = query.Where(sql, where...).Find(&studentList).Error
	if err != nil {
		return err
	}
	//获取全部学生信息
	studentScore := new(model.StudentScore)
	allData := make([]map[string]interface{}, 0)
	for _, stu := range studentList {
		item := make(map[string]interface{}, 0)
		item["school_id"] = schoolId
		item["year"] = request.Year
		item["rule_id"] = request.RuleId
		item["is_spec"] = stu.IsSpec
		item["ksh"] = stu.Ksh
		item["sfzh"] = stu.Sfzh
		item["type_id"] = stu.TypeID
		item["gra_type"] = stu.GraType
		item["stu_name"] = stu.Xm
		item["stu_id"] = stu.ID
		allData = append(allData, item)

		if len(allData) == 200 {
			query.Model(studentScore).Create(allData)
		}
	}

	if len(allData) > 0 {
		query.Model(studentScore).Create(allData)
	}

	return err
}

// ClearStudent 清空学生成绩
func (rev *studentScoreService) ClearStudent() (err error) {
	ruleId := rev.req.Param("rule_id")
	studentScore := new(model.StudentScore)
	err = model.NewDb("").Query().Where("rule_id = ? ", ruleId).Delete(studentScore).Error
	return err
}

// ImportStudentScore 导入学生成绩
func (rev *studentScoreService) ImportStudentScore(request *adminRequest.ImportStudentScoreRequest) (ret interface{}, err error) {
	file := new(model.FileCenter)
	_ = model.NewDb("").FindOne(file, "id = ?", []interface{}{request.FileId}, "*", nil)

	//1.检测zip文件是否存在
	if file.SavePath == "" || libs.FileIsNotExist(filepath.Join(app.YiRanPublicDir, file.SavePath)) == true {
		return nil, errors.New("zip文件不存在")
	}

	_, list, err := service.NewExcelService().ReadExcelXlsx(file.SavePath)
	newList := make([]map[string]interface{}, 0)
	for _, v := range list {
		item := rev.LinkExcelStudentScore(v)
		sfzh, _ := item["sfzh"]
		delete(item, "sfzh")
		delete(item, "stu_name")
		model.NewDb("").Query().Model(&model.StudentScore{}).Where("sfzh = ?", sfzh).Updates(item)
	}

	return newList, err
}

// UpdateRanking 按照分数排序
func (rev *studentScoreService) UpdateRanking() (total int, err error) {
	ruleId := rev.req.Param("rule_id")
	query := model.NewDb("").Query()
	rule := new(model.StudentScoreRule)
	err = query.Where("id = ?", ruleId).First(rule).Error
	if err != nil {
		return
	}
	if rule.RankSort == "" {
		return 0, errors.New("排序规则必须存在")
	}
	//符合规则下的所有的学生按照分数排序
	list := make([]model.StudentScore, 0)
	order := NewScoreRuleService(rev.req).GetRankSort(rule.RankSort)
	err = query.Where("rule_id = ?", ruleId).Order(order).Find(&list).Error

	if err != nil {
		return
	}

	go func() {
		for i := 0; i < len(list); i++ {
			k := i + 1
			query.Where("id = ?", list[i].ID).Model(&model.StudentScore{}).Updates(map[string]interface{}{
				"ranking": k,
			})
		}
	}()

	return len(list), err
}

// LevelGrading 等级转换成分数
func (rev *studentScoreService) LevelGrading() (total int, err error) {
	ruleId := rev.req.Param("rule_id")
	query := model.NewDb("").Query()
	//符合规则下的所有的学生按照分数排序
	list := make([]map[string]interface{}, 0)
	err = query.Model(model.StudentScoreModel).Select("id,level_chinese,level_math,level_english,level_whsz").Where("rule_id = ?", ruleId).Find(&list).Error
	if err != nil {
		return
	}
	level := make([]string, 0)
	level = append(level, "chinese", "math", "english", "whsz")
	for _, stu := range list {
		updateData := make(map[string]interface{}, 0)
		for i := 0; i < len(level); i++ {
			updateData["score_"+level[i]] = rev.LevelToScore(stu["level_"+level[i]].(string))
		}
		err = query.Model(model.StudentScoreModel).Where("id = ?", stu["id"]).Updates(updateData).Error
		if err == nil {
			total++
		}

	}
	return total, err
}

// Grading 分数转换成等级
func (rev *studentScoreService) Grading() (total int, err error) {
	ruleId := rev.req.Param("rule_id")
	query := model.NewDb("").Query()
	//符合规则下的所有的学生按照分数排序
	list := make([]map[string]interface{}, 0)
	err = query.Model(model.StudentScoreModel).Select("id,score_chinese,score_math,score_english,score_whsz").Where("rule_id = ?", ruleId).Find(&list).Error
	if err != nil {
		return
	}
	level := make([]string, 0)
	level = append(level, "chinese", "math", "english", "whsz")
	for _, stu := range list {
		updateData := make(map[string]interface{}, 0)
		for i := 0; i < len(level); i++ {
			updateData["level_"+level[i]] = rev.ScoreToLevel(stu["score_"+level[i]].(float64))
		}
		err = query.Model(model.StudentScoreModel).Where("id = ?", stu["id"]).Updates(updateData).Error
		if err == nil {
			total++
		}

	}
	return total, err
}

// CalScore 计算总成绩
func (rev *studentScoreService) CalScore() (total int, err error) {
	ruleId := rev.req.Param("rule_id")
	query := model.NewDb("").Query()
	rule := new(model.StudentScoreRule)
	err = query.Where("id = ?", ruleId).First(rule).Error
	if err != nil {
		return
	}
	if rule.JsRule == "" {
		return 0, errors.New("排序规则必须存在")
	}
	setSql := NewScoreRuleService(rev.req).GetScoreJsRule(rule.JsRule)
	stuList := make([]model.StudentScore, 0)
	_ = query.Where("rule_id = ?", ruleId).Find(&stuList).Error
	for _, stu := range stuList {
		sql := "UPDATE " + model.ExcelStudentScore{}.TableName() + " SET " + setSql + " WHERE id = ?"
		query.Exec(sql, stu.ID)
	}
	return
}

// LinkExcelStudentScore 处理学生成绩数据
func (rev *studentScoreService) LinkExcelStudentScore(value map[string]interface{}) map[string]interface{} {
	excelStudentScore := new(model.ExcelStudentScore)
	p := reflect.TypeOf(excelStudentScore).Elem()
	data := make(map[string]interface{}, 0)

	for i := 0; i < p.NumField(); i++ {
		jsonTag := p.Field(i).Tag.Get("json")
		ecl := p.Field(i).Tag.Get("exl")
		//获取map中的值
		v, ok := value[ecl]
		if !ok {
			// 如果 value[ecl] 不存在，为 data[jsonTag] 赋予默认值 0.00
			data[jsonTag] = 0.00
			continue
		}

		// 如果 value[ecl] 存在且其值为 nil 或 空字符串，为 data[jsonTag] 赋予默认值 0.00
		if v == nil || v.(string) == "" {
			data[jsonTag] = 0.00
			continue
		}

		// 若 value[ecl] 存在且有有效值，则将其值赋给 data[jsonTag]
		data[jsonTag] = v
	}
	return data
}

// LevelToScore 等级转成分数
func (rev *studentScoreService) LevelToScore(level string) (score float64) {
	switch strings.ToUpper(level) {
	case "A":
		score = 90
	case "B":
		score = 80
	case "C":
		score = 70
	case "D":
		score = 60
	case "E":
		score = 50
	case "F":
		score = 40
	default:
		score = 30

	}

	return score
}

// ScoreToLevel 等级转成分数
func (rev *studentScoreService) ScoreToLevel(score float64) (level string) {
	switch {
	case score >= 90:
		level = "A"
	case score >= 80:
		level = "B"
	case score >= 70:
		level = "C"
	case score >= 60:
		level = "D"
	case score >= 50:
		level = "E"
	default:
		level = "F"
	}

	return level
}

// Assignment 模拟赋分
func (rev *studentScoreService) Assignment() (err error) {

	ruleId := rev.req.Param("rule_id")
	sql := "UPDATE " + model.StudentScoreTable + " SET `score_whsz` = FLOOR(RAND() * 99) + 1 "
	sql += " WHERE rule_id = ?"
	err = model.NewDb("").Query().Exec(sql, ruleId).Error

	return
}

func NewStudentScoreService(request *gin.Context) *studentScoreService {
	return &studentScoreService{
		req: request,
	}
}
